package com.ufaud.ais.sys.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ufaud.ais.pub.dao.IGenericCRUDDao;
import com.ufaud.ais.pub.exception.BusinessException;
import com.ufaud.ais.pub.service.impl.GenericCRUDServiceImpl;
import com.ufaud.ais.pub.utils.SetUtil;
import com.ufaud.ais.sys.dao.IMenuItemDao;
import com.ufaud.ais.sys.entity.Employee;
import com.ufaud.ais.sys.entity.MenuItem;
import com.ufaud.ais.sys.entity.Role;
import com.ufaud.ais.sys.service.IMenuItemService;

public class MenuItemServiceImpl extends GenericCRUDServiceImpl<MenuItem, Long> implements IMenuItemService {

	private static Log LOG = LogFactory.getLog(MenuItemServiceImpl.class);

	private IGenericCRUDDao<Employee, Long> employeeDao;

	public MenuItemServiceImpl(IMenuItemDao menuItemDao, IGenericCRUDDao<Employee, Long> employeeDao) {
		super(menuItemDao);
		this.employeeDao = employeeDao;
	}

	private IMenuItemDao getDao() {
		return (IMenuItemDao) iGenericCRUDDao;
	}

	public MenuItem getMenuItemWithSuperMenuItem(Long id) {
		MenuItem menuItem = getDao().get(id);
		getDao().initSuperMenuItem(menuItem);
		return menuItem;
	}

	public void deleteMenuItemById(Long id) throws BusinessException {
		MenuItem persistedMenuItem = getDao().get(id);
		List<MenuItem> subDeptList = persistedMenuItem.getSubMenuItemList();
		if (subDeptList != null && subDeptList.size() > 0) {
			throw new BusinessException("【" + persistedMenuItem.getMenuItemName() + "】尚有子菜单项，无法删除");
		} else {
			getDao().remove(id);
		}
	}

	public MenuItem getAllMenuItemInTreeStructure() {
		List<MenuItem> menuItemList = getDao().findByNamedQuery("getMenuTree", new HashMap<String, Object>());
		MenuItem rootMenu = new MenuItem();
		rootMenu.setMenuItemName("菜单");
		for (MenuItem menuItem : menuItemList) {
			getDao().recInitSubMenuItem(menuItem);
			getDao().evict(menuItem);
			rootMenu.addMenuItem(menuItem);
		}
		return rootMenu;
	}

	public List<MenuItem> getAncestorAndSiblingMenuItemById(Long id) {
		List<MenuItem> selfAndDescentantsList = getMenuItemWithDescendantsById(id);
		List<MenuItem> resultList = getAll();
		resultList.removeAll(selfAndDescentantsList);
		return resultList;
	}

	public List<MenuItem> getMenuItemWithDescendantsById(Long id) {
		MenuItem menuItem = getDao().get(id);
		List<MenuItem> resultList = new ArrayList<MenuItem>();
		recLoadSubMenuItemToList(menuItem, resultList);
		return resultList;
	}

	private void recLoadSubMenuItemToList(MenuItem menuItem, List<MenuItem> list) {
		list.add(menuItem);
		List<MenuItem> menuItemList = menuItem.getSubMenuItemList();
		if (menuItemList != null && menuItemList.size() > 0) {
			for (MenuItem oneSubMenuItem : menuItemList) {
				recLoadSubMenuItemToList(oneSubMenuItem, list);
			}
		}
	}

	@Override
	public Long save(MenuItem menuItem) {
		if (menuItem.getSuperMenuItem() == null) {
			LOG.debug("level = 0");
			menuItem.setMenuItemLevel(0);
		} else {
			Long superId = menuItem.getMenuItemId();
			MenuItem superMenuItem = getDao().get(superId);
			int newLevel = superMenuItem.getMenuItemLevel() + 1;
			menuItem.setMenuItemLevel(newLevel);
			LOG.debug("level = " + newLevel);
			// menuItem.setSuperMenuItem(superMenuItem);
		}
		return super.save(menuItem);
	}

	public void updateMenuItem(MenuItem menuItem) {
		Long id = menuItem.getMenuItemId();
		MenuItem persistedMenuItem = getDao().get(id);
		persistedMenuItem.setMenuItemName(menuItem.getMenuItemName());
		persistedMenuItem.setMenuItemTarget(menuItem.getMenuItemTarget());
		if (menuItem.getSuperMenuItem() == null) {
			menuItem.setMenuItemLevel(0);
			LOG.debug("level = 0");
			// menuItem.setSuperMenuItem(null);
		} else {
			Long superId = menuItem.getMenuItemId();
			MenuItem superMenuItem = getDao().get(superId);
			int newLevel = superMenuItem.getMenuItemLevel() + 1;
			persistedMenuItem.setMenuItemLevel(newLevel);
			LOG.debug("level = " + newLevel);
			// persistedMenuItem.setSuperMenuItem(superMenuItem);
		}
	}

	public List<MenuItem> getMenuItemListInTreeStructureByUserId(Long id) {
		Employee employee = employeeDao.get(id);
		Set<MenuItem> menuItemSet = SetUtil.<MenuItem> getSetOrderedByBeanProperty(new String[] { "menuItemId", "menuItemLevel" }, new boolean[] { true, true },
				new boolean[] { false, false });
		Set<Role> roles = employee.getRoleSet();
		for (Role oneRole : roles) {
			menuItemSet.addAll(oneRole.getMenuItemSet());
		}
		// 初始化每个menuItem的父类，并把menuItem evict出来以便后边的操作不再与数据库互动
		for (MenuItem menuItem : menuItemSet) {
			getDao().initSuperMenuItem(menuItem);
			getDao().evict(menuItem);
			menuItem.setSubMenuItemList(new ArrayList<MenuItem>());
		}
		
		List<MenuItem> resultList = new ArrayList<MenuItem>();
		for (MenuItem menuItem : menuItemSet) {
			MenuItem superMenuItem = menuItem.getSuperMenuItem();
			if(superMenuItem != null) { // 有上级菜单的，说明不是顶级的菜单
				superMenuItem.addMenuItem(menuItem);
			} else if(menuItem.getMenuItemLevel() == 0){ // 顶级菜单
				resultList.add(menuItem);
			} else {
				LOG.warn("菜单项："+menuItem+"缺少顶级父菜单，无效");
			}
		}
		return resultList;
	}

}
